//
//  ElasticShapeLayer.m
//  练习_11.04_1
//
//  Created by rimi1 on 2016/11/4.
//  Copyright © 2016年 Wangxingqian. All rights reserved.
//

#import "ElasticShapeLayer.h"
#import <UIKit/UIBezierPath.h>// 导入这个才能用UIBezierPath

@interface ElasticShapeLayer () <CAAnimationDelegate>

@property (nonatomic, assign) NSInteger count;
@property (nonatomic, assign) CGSize size;// 视图大小
@property (nonatomic, assign) CGFloat elastic;// 弹性值
@property (nonatomic, assign) NSInteger elasticCount;// 弹性次数
@property (nonatomic, assign) CGFloat circular;// 圆角值
@property (nonatomic, assign) BOOL isAnimation;// 记录是否继续动画，YES为停止动画

@end

@implementation ElasticShapeLayer

- (instancetype)initWithSize:(CGSize)size elastic:(CGFloat)elastic elasticCount:(NSInteger)elasticCount circular:(CGFloat)circular fillColor:(CGColorRef)fillColor {
    self.size = size;
    self.elastic = elastic;
    self.elasticCount = elasticCount;
    self.circular = circular;
    self.fillColor = fillColor;
    
    CGFloat width = size.width;
    CGFloat height = size.height;
    
    UIBezierPath *bezier = [UIBezierPath bezierPath];
    [bezier moveToPoint:CGPointMake(circular, 0)];
    [bezier addLineToPoint:CGPointMake(width - circular, 0)];
    [bezier addQuadCurveToPoint:CGPointMake(width, circular) controlPoint:CGPointMake(width, 0)];
    [bezier addLineToPoint:CGPointMake(width, height - circular)];
    [bezier addQuadCurveToPoint:CGPointMake(width - circular, height) controlPoint:CGPointMake(width, height)];
    [bezier addLineToPoint:CGPointMake(circular, height)];
    [bezier addQuadCurveToPoint:CGPointMake(0, height - circular) controlPoint:CGPointMake(0, height)];
    [bezier addLineToPoint:CGPointMake(0, circular)];
    [bezier addQuadCurveToPoint:CGPointMake(circular, 0) controlPoint:CGPointMake(0, 0)];
    [bezier closePath];
    
    self.path = bezier.CGPath;
    
    return self;
}

#pragma mark - Method

- (void)showAnimation {
    // 判断应不应该执行动画(最后一次self.isAnimation == YES，所以不继续执行动画，相当于停止动画)
    if (!self.isAnimation) {
        [self animation];
    }else {
        // 可以再次调用动画
        self.isAnimation = NO;
    }
}
// 动画
- (void)animation {
    CGFloat width = self.size.width;
    CGFloat height = self.size.height;
    // 计算弹性值
    CGFloat transForm = [self elasticityCalculate];
    
    CABasicAnimation *basic = [CABasicAnimation animation];
    // 要改变的属性
    basic.keyPath = @"path";
    // 初始值
    basic.fromValue = (__bridge id _Nullable)(self.path);
    // 动画时间
    basic.duration = 0.15;
    basic.delegate = self;
    // 改变形状
    UIBezierPath *bezier = [UIBezierPath bezierPath];
    // 左上角为起点
    [bezier moveToPoint:CGPointMake(self.circular, 0)];
    [bezier addQuadCurveToPoint:CGPointMake(width - self.circular, 0) controlPoint:CGPointMake(width/2, -transForm)];
    // 右上角
    [bezier addQuadCurveToPoint:CGPointMake(width, self.circular) controlPoint:CGPointMake(width, 0)];
    [bezier addQuadCurveToPoint:CGPointMake(width, height - self.circular) controlPoint:CGPointMake(width + transForm, height/2)];
    // 右下角
    [bezier addQuadCurveToPoint:CGPointMake(width - self.circular, height) controlPoint:CGPointMake(width, height)];
    [bezier addQuadCurveToPoint:CGPointMake(self.circular, height) controlPoint:CGPointMake(width/2, height + transForm)];
    // 左下角
    [bezier addQuadCurveToPoint:CGPointMake(0, height - self.circular) controlPoint:CGPointMake(0, height)];
    [bezier addQuadCurveToPoint:CGPointMake(0, self.circular) controlPoint:CGPointMake(-transForm, height/2)];
    // 左上角
    [bezier addQuadCurveToPoint:CGPointMake(self.circular, 0) controlPoint:CGPointMake(0, 0)];
    // 闭合路径
    [bezier closePath];
    
    // 添加动画
    self.path = bezier.CGPath;
    [self addAnimation:basic forKey:nil];
    
    self.count++;
}

// 弹性值计算
- (CGFloat)elasticityCalculate {
    // 最后一次变形(因为这个计算是在动画里面调用，所以 -1 得真正的次数)
    if (self.count == self.elasticCount - 1) {
        // 改变状态不再继续调用动画，并且返回0，也就是变化为初始形状
        self.isAnimation = YES;
        self.count = 0;
        return 0;
    }
    // 取余2， 0 为正， 1 为负
    NSInteger a = self.count % 2;
    // 基础变形倍数(越大弹性越小)
    NSInteger b = 4;
    // a == 0 增大， a == 1 缩小 (缩小就是取反)
    if (a == 1) {
        b = -(b + self.count);
    }else {
        b += self.count;
    }
    
    // 基础值/弹性倍数
    return self.elastic/b;
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
    [self showAnimation];
}

@end













